import gugga.events.EventDispatcher;
import mx.utils.Delegate;

import com.mosesSupposes.fuse.FuseItem;
import com.mosesSupposes.fuse.FuseKitCommon;

/**
*
* The Fuse Kit [build1.1z3]
* Copyright (c) 2006 Moses Gunesch, MosesSupposes.com
* 
* Distributed under MIT Open Source License, see Fuse-Kit-License.html (in fuse package directory)
* Easing Equations (c) 2003 Robert Penner used by permission, see PennerEasing
* Visit http://www.mosessupposes.com/Fuse
* 
* @ignore
*
* Event & animation sequencer that extends Array.
* <br><br>
* @usage
* To enable animation sequencing, pass Fuse to {@link com.mosesSupposes.fuse.ZigoEngine#register} or {@link com.mosesSupposes.fuse.ZigoEngine#simpleSetup}.
* <br><br>
* Events dispatched:
* <ul><li><code>onStart</code></li><li><code>onStop</code></li><li><code>onPause</code></li><li><code>onResume</code></li><li><code>onAdvance</code></code></li><li><code>onComplete</code></li></ul>
* <br>Unlike ZigoEngine which uses AsBroadcaster, Fuse uses the mx EventDispatcher standard.
* <pre>var f:Fuse = new Fuse();
* f.addEventListener("onComplete", myListenerObj);</pre>
* <br>
* The Fuse utility is comprised of:
* <ul>
* <li>Class & instance default settings</li>
* <li>Array methods (see {@link #push})</li>
* <li>Play-control methods (see {@link #start})</li>
* <li>Simple Syntax static methods (see {@link #open})</li>
* <li>A runtime Object Syntax interpreter (see {@link #Fuse})</li>
* <li>Instance management methods (see {@link #getInstance})</li>
* </ul>
* <br>
* Fuse Object Syntax parameters are documented under the {@link #Fuse} constructor.<br>
* <br>
* Fuse Simple Syntax parameters are documented under Fuse.{@link #open}.
* 
* @author	Moses Gunesch / MosesSupposes.com
* @version	2.0
*/
class com.mosesSupposes.fuse.Fuse extends Array
{
	/**
	 * @exclude
	 * Unique identifier used by ZigoEngine.register
	 */ 
	public static var registryKey:String = 'fuse';
	
	/**
	 * Class default: Enables kit version to be retrieved at runtime or when reviewing a decompiled swf. 
	 */
	public static var VERSION:String = FuseKitCommon.VERSION;
	
	/**
	* Class default: Controls how much feedback Fuse outputs, helpful for debugging.
	* @usage
	* <ul>
	* <li>0 = no traces,</li> 
	* <li>1 = normal errors & warnings</li>
	* <li>2 = additional Fuse output</li>
	* <li>3 = additional FuseItem output</li>
	* </ul>
	*/
	public static var OUTPUT_LEVEL:Number = 1;
	
	/**
	 * Class default: whether Fuse instances are automatically destroyed after playing once unless otherwise specified by instance-level {@link #autoClear}.
	 * @usage When a Fuse is set to auto-remove itself it is best practice to not set a variable reference to that Fuse, which may cause memory buffering, or to delete the variable when the Fuse is complete.<br><br>
	 * To override this default on a per-Fuse basis set the instance's {@link #autoClear} property.
	 * @see #autoClear
	 */ 
	public static var AUTOCLEAR:Boolean = false; 
	
	/**
	 * Instance default: Convenience, allows you to name any Fuse.
	 * @description	The Fuse label is used in output messages, and can be used to reference a Fuse instance in {@link #getInstance} and Simple Syntax methods {@link #open} and {@link #openGroup}.
	 * @see #id
	 * @see #getInstance
	 * @see #open
	 * @see #openGroup
	 */
	public var label:String; 
	
	/**
	 * Instance default: Fuse instance is automatically destroyed after playing once.
	 * @usage
	 * <pre>var f:Fuse = new Fuse();
	 * f.autoClear = true;</pre>
	 * In this example, the fuse instance f will delete itself after it plays through once, at which time you should also delete the variable <code>f</code> to prevent memory buffering issues.
	 * @see #AUTOCLEAR
	 */ 
	public var autoClear:Boolean = false; 
	
	/**
	 * Instance default: scope for all functions run from a Fuse if left unspecified within the action.
	 * @usage
	 * <pre>var f:Fuse = new Fuse();
	 * f.scope = this;
	 * f.push({target:menu, 
	 * 	start_alpha:0,
	 * 	x:getMenuX,
	 * 	y:getMenuY, 
	 * 	startfunc:"setupMenu", 
	 * 	updfunc:"onMenuFadeUpdate", 
	 * 	func:"onMenuShown"
	 * });
	 * f.push({ scope:contentArea,
	 * 	func:"drawContent"
	 * });</pre>
	 * In this example, all the functions in the first action, including the runtime-evaluation calls to supposed getMenuX and getMenuY methods will be 
	 * auto-scoped to the Fuse's default scope (this). In the second action, drawContent is specifically scoped to the contentArea object, overriding the default.
	 * It's most useful to set a default scope when there will be many function calls within the sequence, to save you from specifically scoping each action.
	 * @see #Fuse
	 */ 
	public var scope:Object;
	
	/**
	 * Internal id based on instance count. 
	 */
	private var _nID:Number;
	
	/**
	 * Internal sequence play-index. 
	 */
	private var _nIndex:Number;
	
	/**
	 * Internal, can be "stopped", "playing", or "paused".
	 */
	private var _sState:String = 'stopped';
	
	/**
	 * Internal list of instance's default animation targets, set using public setter target or addTarget method.
	 */ 
	private var _aDefaultTargs:Array;
	
	/** 
	 * Internal setInterval id for delays run by Fuse. (Delays in groups or with tweens are handled by FuseItem.)
	 */
	private var _nDelay:Number = -1;
	
	/**
	 * Internal storage used for tracking a delay's current time during pause().
	 */ 
	private var _nTimeCache:Number = -1;
	
	/**
	 * Stores a Delegate function used to trap nested Fuse's onComplete event (stored for later removal during destroy()).
	 */ 
	private var _oDel1:Object;
	
	/**
	 * Static list of all Fuse instances created, publicly accessible via getInstance() and getInstances() and used by remote methods like open().
	 */ 
	private static var _aInstances:Array = null;
	
	/**
	 * Internal storage of Build Mode (Simple Syntax) params curID:Number (often queried to find out if Build Mode is active), prevID:Number, curGroup:Array.
	 */ 
	private static var _oBuildMode:Object = null;
	
	/**
	 * Written in during EventDispatcher.initialize().
	 */ 
	private var dispatchEvent:Function;
	
	/**
	* Fuse extends Array to enable sequence-building & mangaement using familiar methods like <code>push()</code>.
	* @param action		One or more generic "action" objects or arrays in Fuse Object Syntax constituting a sequence.
	* @usage
	* <pre>
	* var f:Fuse = new Fuse(
	*  {start_x:'-50', start_xscale:150, start_alpha:0, seconds:.5 },
	*  [ 
	*   { width:500, ease:'easeInExpo', seconds:1 },
	*   { height:300, ease:'easeInOutExpo', delay:.5 }
	*  ]);
	* f.target = box1_mc;
	* f.start();
	* 
	* f.traceItems();</pre>
	* Outputs:
	* <pre>-Fuse#0 traceItems:
	* ----------
	* Fuse#0>Item#0: StartProps:[_alpha, _xscale, _x] Props:[_x, _xscale, _alpha]
	* Fuse#0>Item#1: Props:[_height, _width]
	* ----------</pre>
	* <br>
	* Fuse action objects may be:
	* <ul><li>Generic objects containing parseable properties<br>
	* <code>{ target:clip1, x:10, seconds:2, ease:Strong.easeInOut }</code></li>
	* <li>An array of such action objects which creates a simultaneous tween group<br>
	* <code>[ { x:10, seconds:2, ease:Strong.easeInOut }, { start_alpha:0, seconds:.5 } ]</code><br></li>
	* <li>A nested Fuse<br></li>
	* <li>"Applied actions": a special format for reusing actions by including an <code>action</code> property.<br><br>
	* For example if an action <code>var intro:Object = { ... }</code> has been defined, 
	* you can then include it in later Fuse actions like this:<br>
	* <code>{ target:clip1, action:intro }</code><br><br>
	* This lets you build multi-purpose behaviors that can be used with different targets, perhaps a custom fade or movement effect.<br>
	* Applied actions may contain the following properties that modify the base action:<br> 
	* <code>delay, target, addTarget, label, trigger</code>.<br>
	* While <code>target</code> overrides, <code>addTarget</code> concatenates targets with any that are defined in the action. See below for info on others.</li>
	* </ul>
	* <br>
	* Fuse action-object properties may be:
	* <ul><li><b>Parseable properties</b>, listed below</li>
	* <li><b>Any custom property</b> you wish to tween (should be pre-declared and set to a number)</li>
	* <li><b>Start values:</b> Prepend <code>start_</code> to any property and it will be set prior to tweening.</li></ul>
	* <br>
	* Fuse action-object values may be types:
	* <ul><li><b>Number</b> - a tween's end position. <code>x:100</code></li>
	* <li><b>String</b> - calculate tween using <b>relative</b> positioning.<br>
	* Example: <code>rotation:"-90"</code> yields a counter-clockwise rotation.</li>
	* <li><b>Boolean</b> values, set at start or end of tween.<br>
	* Example: <code>start_visible:true</code></li>
	* <li><b>Tint</b> values can be Number (<code>0x000000</code>), String (<code>"#000000"</code>), or <code>null</code> (reset)<br>
	* Example: <code>tint:"#FF3300"</code></li>
	* <li><b>Time</b> is specified in seconds, and may be Number or timecode-String format.<br>
	* Examples: <code>seconds:2</code>, <code>startAt:"01:75"</code> - timecode for a 1.75-second delay</li>
	* <li><b>Function</b> - (Advanced) "Runtime evaluation" - function is queried as the action is played in the sequence. 
	* Functions should return values appropriate to the property.<br>
	* Example: <code>{ x:function(){ return _root._xmouse; } }</code><br>
	* <br>
	* This is a powerful feature that helps eliminate the need to hardcode values in advance. 
	* Fuses can be written to be "live", querying for targets and values themselves by retrieving state variables from within your program.<br>
	* <br>
	* Such functions will be scoped first to the action then the Fuse instance's <code>scope</code> property.  
	* If <code>scope</code> is already being used for callbacks, you can use a Delegate to individually scope runtime-evaluation functions.</li>
	* </ul>
	* <br>
	* <b>Parseable action properties</b>
	* <br><br>
	* <ul><li><code>label</code> String naming the action, that may be used during {@link #skipTo} and viewed in output messages. (This property cannot be set to a function value)</li>
	* <li><code>target</code> Animation target or Array of targets. Overrides the instance's default {@link #target} list.</li>
	* <li><code>addTarget</code> Concatenates one or an Array of targets with the default {@link #target} list.</li>
	* <li><code>ease or easing</code> Accepts same formats as {@link com.mosesSupposes.fuse.ZigoEngine#doTween}'s easing parameter.</li>
	* <li><code>seconds, time or duration</code> See time formatting above.</li>
	* <li><code>delay or startAt</code> See time formatting above.</li>
	* <li><code>event</code> String declaring a custom event that should be dispatched by the engine.<br>
	* Subscribe to this custom event on the Fuse instance the same as you would for built-in events (see header).</li>
	* <li><code>eventparams</code> An object whose properties will be copied to the event object dispatched with the custom event. (Requires that the <code>event</code> property is defined)</li>
	* <li><code>func</code> Function or string name of function</li>
	* <li><code>scope</code> Object - overrides instance default {@link #scope}. Note that in Fuse actions this property is special in that it will be applied to all callbacks or runtime-evaluation functions if not otherwise defined.</li>
	* <li><code>args</code> One argument or an array of arguments to pass to the <code>func</code> callback.</li>
	* <li><code>startfunc</code> Callback fired after any delay and as tween is starting.</li>
	* <li><code>startscope</code> If not defined, the <code>scope</code> property or instance default {@link #scope} will be used.</li>
	* <li><code>startargs</code> One argument or an array of arguments to pass to the <code>startfunc</code> callback.</li>
	* <li><code>updfunc</code> Callback fired on engine pulse as the tweens in the action are updated.</li>
	* <li><code>updscope</code> If not defined, the <code>scope</code> property or instance default {@link #scope} will be used.</li>
	* <li><code>updargs</code> One argument or an array of arguments to pass to the <code>updfunc</code> callback.</li>
	* <li><code>easyfunc</code> String like <code>"myClip.doSomething(true);"</code>. ({@link com.mosesSupposes.fuse.Shortcuts} must be registered to use this feature)</li>
	* <li><code>extra1</code> Elastic easing amplitude or Back easing overshoot</li>
	* <li><code>extra2</code> Elastic easing period</li>
	* <li><code>_bezier_</code> (Not necessary, see controlX, controlY below.) Generic object with some or all of the properties <code>{x:,y:,controlX:,controlY:}</code>. Relative (string) values are okay. Note that only one control param is necessary to generate a curved motion path.</li>
	* <li><code>controlX, controlY</code> Including one or both of these parameters in a Fuse along with x and/or y generates a bezier curve similar to using the _bezier_ property but without the need for a nested object.</li>
	* <li><code>cycles</code> An integer 2 or higher, tweens back and forth between start and end positions. Infinite cycles (0 or "LOOP" in {@link com.mosesSupposes.fuse.ZigoEngine#doTween}) are not allowed in Fuses.</li>
	* <li><code>skipLevel</code> 0,1, or 2.  See {@link com.mosesSupposes.fuse.ZigoEngine#SKIP_LEVEL} for details. In Fuse, this parameter also applies to the custom <code>event</code> parameter, although standard Fuse events like <code>onComplete</code> are not skipped.</li>
	* <li><code>trigger</code> May be set as seconds (see time formatting above) or set to <code>true</code> if in a group to indicate advance after the item trigger is grouped with.<br>
	* Advances the sequence prior to action completion. This is a powerful feature that makes sequencing far less rigid and more timeline-like.<br>
	* Example 1: In this group the sequence advances after the fade action.
	* <code>[ { start_alpha:0, seconds:.5, trigger:true}, { x:'100', seconds:3 } ]</code><br>
	* Example 2: Here the sequence advances after 1.5 seconds, while the action takes 3 seconds.
	* <code>{ width:500, delay:1, seconds:2, trigger:1.5 }</code><br><br>
	* Note that the <code>onComplete</code> Fuse event is not fired until any trailing tweens from triggered actions finish.</li>
	* <li><code>command</code> String <code>"start","stop","pause","resume","skipTo","setStartProps"</code>.<br>
	* Allows actions to control Fuse play.<br>
	* Example: a final action of <code>{command:"start"}</code> causes the Fuse to loop.<br>
	* Commands should be separate actions. They may not appear within action groups or be blocked with tweens or callbacks.<br>
	* Actions containing a <code>command</code> property may ONLY contain the additional properties: <code>scope, args, label, delay</code>.<br>
	* Note that any arguments in <code>args</code> are sent to the Fuse command, and <code>scope</code> is only used for runtime-evaluation of other params set to function (see "Runtime-evaluation" above).</li>
	* </ul>
	* <br>
	* Unless you have set <code>FuseItem.ADD_UNDERSCORES</code> to false, the following known properties are underscore-optional:
	* <ul>
	* <li><code>_alpha or alpha</code></li>
	* <li><code>_rotation or rotation</code></li>
	* <li><code>_x or x</code></li>
	* <li><code>_y or y</code></li>
	* <li><code>_xscale or xscale</code></li>
	* <li><code>_yscale or yscale</code></li>
	* <li><code>_scale or scale</code> Sets _xscale and _yscale to the same value</li>
	* <li><code>_width or width</code></li>
	* <li><code>_height or height</code></li>
	* <li><code>_size or size</code> Sets _width and _height to the same value</li>
	* <li><code>_frame or frame</code> Tweens a MovieClip's timeline to a frame using easing specified.</li>
	* <li><code>_tint or tint</code> Tint formats above or object <code>{tint:Number/null/hexString, percent:Number/String}</code>.</li>
	* <li><code>_tintPercent or tintPercent</code> Value range 0-100</li>
	* <li><code>_brightness or brightness</code> Value range 0-100</li>
	* <li><code>_brightOffset or brightOffset</code> Burn effect. -100=black, 0=normal, 100=white</li>
	* <li><code>_invertColor or invertColor</code> Value range 0-100</li>
	* <li><code>_colorReset or colorReset</code> Value ranges from 0 (current tint) to 100 (full reset).</li>
	* <li><code>_contrast or contrast</code> 0=gray, 100=normal, 200=high-contrast, higher=posterized</li>
	* <li><code>_colorTransform or colorTransform</code> Flash7 transform object <code>{ra:,rb:,etc.}</code></li>
	* <li><code>_visible or visible</code></li>
 	* </ul>
 	* @see #target
 	* @see #scope
 	* @see #push
 	* @see #pushTween
 	* @see #open
	*/
	function Fuse (action:Object)
	{
		EventDispatcher.initialize(this);
		this._nID = registerInstance(this); // Fuse identifier retrievable using the ID property
		this._sState = 'stopped';
		this._aDefaultTargs = new Array();
		if (arguments.length>0) {
			this.splice.apply(this, ((new Array(0, 0)).concat(arguments)));
		}
		// retroactively disable some Array methods - this technique conserves filesize.
		var unsupport:Array = ['concat','join','sort','sortOn'];
		for (var i:String in unsupport) Fuse.prototype[unsupport[i]] = function() { if (Fuse.OUTPUT_LEVEL>0) FuseKitCommon.error('105'); };
	}
	
	/**
	 * This function is overwritten during EventDispatcher.initialize(). 
	 * @ignore
	 * Add a listener for a particular event
	 * @param event the name of the event ("onComplete", etc)
	 * @param the function or object that should be called
	 * @see #removeEventListener
	 */
	public function addEventListener(event:String, handler:Object):Void {}
	
	/**
	 * This function is overwritten during EventDispatcher.initialize(). 
	 * @ignore
	 * Remove a listener for a particular event
	 * @param event the name of the event ("onComplete", etc)
	 * @param the function or object that should be called
	 * @see #addEventListener
	 */
	public function removeEventListener(event:String, handler:Object):Void {}
	
	/**
	* Deletes all variables and properties in the Fuse instance. 
	* @usage
	* You should remove all listeners before calling destroy(), then after the call delete any variable references to the instance cleared.
	* <pre>
	* myFuse.removeEventListener('onComplete',this);
	* myFuse.destroy();
	* delete myFuse;
	* </pre>
	* @see #autoClear
	* @see #AUTOCLEAR
	* @see #getInstance
	*/
	public function destroy():Void
	{
		if (Fuse.OUTPUT_LEVEL>1) FuseKitCommon.output('-Fuse#'+String(_nID)+' destroy.');
		this.stop(true);
		splice(0,length);
		_aDefaultTargs = null;
		scope = null;
		// required for stripping listeners. 0,7 is not a mistake - do not change
		_global.ASSetPropFlags(this,null,0,7); 
		var id:Number = _nID;
		for (var i:String in this) delete this[i];
		removeInstanceAt(id, true);
		delete id;
		delete this;
	}
	
	/**
	* Deprecated. Returns error from FuseKitCommon.
	* @deprecated		Use new setup options: {@link com.mosesSupposes.fuse.ZigoEngine#register} or {@link com.mosesSupposes.fuse.ZigoEngine#simpleSetup}.
	*/
	public static function simpleSetup():Void { FuseKitCommon.error('101'); }
	
	/**
	* Instance-management: Gets a Fuse instance by its id or label
	* @description	This simple method returns one known Fuse instance. For more complex options use {@link #getInstances}.
	* @param idOrLabel 		Fuse's numerical {@link #id} or {@link #label} identifying a unique Fuse instance.
	* @return				a Fuse instance if found or null if not
	* @see #getInstances
	*/
	public static function getInstance(idOrLabel:Object):Fuse
	{
		if (typeof idOrLabel=='number') return _aInstances[idOrLabel];
		if (typeof idOrLabel=='string') {
			for (var i:String in _aInstances) if (Fuse(_aInstances[i]).label==idOrLabel) return _aInstances[i];
		}
		return null;
	}
	
	/**
	* Instance-management: Get an array of some or all Fuse instances in active memory, with filtering options.
	* @description 
	* <pre>// get currently playing Fuses that handle the target my_mc
	* var myMcFuses:Array = Fuse.getInstances("playing",my_mc);
	* // get all the Fuses in active memory
	* var fuses:Array = Fuse.getInstances();</pre>
	* @param stateFilter		nothing/null/{@link com.mosesSupposes.fuse.FuseKitCommon#ALL} for all Fuse instances in active memory, or a play state "playing", "stopped" or "paused"
	* @param targets			optional - a single target, an Array of targets, or a list of targets starting with the second param.
	* @return					an array containing one or more Fuse instances matching search criteria
	* @see	#getInstance
	*/
	public static function getInstances(stateFilter:String, targets:Object):Array
	{
		var all:Boolean = (stateFilter==null || (stateFilter.toUpperCase())=='ALL');
		if (!(targets instanceof Array)) targets = arguments.slice(1);
		var a:Array = [];
		for (var i:String in _aInstances) {
			var instance:Fuse = _aInstances[i];
			if (_aInstances[i]==null) continue;
			// if specified state does not match
			if (all==false && instance.state!=stateFilter) continue; 
			// yes: state matches and no targets to filter by
			var found:Boolean = (targets.length==0); 
			if (found==false) {
				// AS2 bug, break does not work twice!
				if (found==true) continue;
				var instTargs:Array = instance.getActiveTargets(true);
				for (var j:String in targets) {
					for (var k:String in instTargs) {
						// yes: a target passed in was found in the instance
						if (instTargs[k]==targets[j]) { 
							found = true;
							break;
						}
					}
				}
			}
			if (found==true) a.unshift(instance);
		}
		return a;
	}
	
	/**
	* Instance default: an auto-assigned numerical reference
	* @return Internal id based on instance count.
	* @see #label
	* @see #getInstance
	*/
	public function get id():Number { return _nID; }	
	
	/**
	* Retrieves a Fuse instance's current play-state string. 
	* @return <code>"stopped", "playing", or "paused"</code>
	* @see #currentIndex
	*/
	public function get state():String { return _sState; }
	
	/**
	* Retrieves the current play-index of a Fuse instance.
	* @return A number starting at 0 for the first action
	* @see #state
	* @see #currentLabel
	*/ 
	public function get currentIndex():Number { return this._nIndex; } 
	
	/**
	* Retrieves the currently playing action's label, if defined.
	* @description <pre>{ label:"introFade", start_alpha:0, start_brightOffset:100, time:1.5, ease:"easeInExpo" }</pre>
	* @return A string set in the action object using the label property.
	* @see #Fuse
	* @see #label
	* @see #state
	* @see #currentIndex
	*/
	public function get currentLabel():String { return (FuseItem(this[_nIndex]).getLabel()); }
	
	/**
	 *  see set target
	 *  @ignore
	 */
	public function get target():Object { return (_aDefaultTargs.length==1) ? _aDefaultTargs[0] : _aDefaultTargs; }
	
	/**
	* Instance default: Sets one or more animation targets that will be used for any actions that don't specify their own.
	* @description Overwrites prior existing targets.
	* <pre>var f:Fuse = new Fuse();
	* f.target = [clip1, clip2];</pre>
	* @param  one target or an array of targets
	* @return a single animation target if one is set or an Array of targets if more than one is set.
	* @see #addTarget
	* @see #removeTarget
	* @see #getActiveTargets
	*/
	public function set target(t:Object):Void {
		delete _aDefaultTargs;
		if (t!=null) {
			addTarget(t);
		}
	}
	
	/**
	* Adds to current default target list.
	* @description <pre>myFuse.addTarget(clip5);</pre>
	* @param  accepts one or more targets, or an array of targets
	* @see #target
	* @see #removeTarget
	* @see #getActiveTargets
	*/
	public function addTarget(t:Object):Void
	{
		if (_aDefaultTargs==null) this._aDefaultTargs = [];
		if (arguments[0] instanceof Array) arguments = arguments[0];
		for (var i:String in arguments) {
			var found:Boolean = false;
			for (var j:String in _aDefaultTargs) {
				if (arguments[i]==_aDefaultTargs[j]) {
					found = true;
					break;
				}
			}
			if (found==false) _aDefaultTargs.push(arguments[i]);
		}
	}
	
	/**
	* Removes targets from the current default target list.
	* @description <pre>myFuse.removeTarget(clip5);</pre>
	* @param  accepts one or more targets, or an array of targets
	* @see	#target
	* @see	#addTarget
	* @see #getActiveTargets
	*/
	public function removeTarget(t:Object):Void
	{
		if (_aDefaultTargs==null || _aDefaultTargs.length==0) return;
		if (arguments[0] instanceof Array) arguments = arguments[0];
		for (var i:String in arguments) {
			for (var j:String in _aDefaultTargs) {
				if (arguments[i]==_aDefaultTargs[j]) _aDefaultTargs.splice(Number(j),1);
			}
		}
	}
	
	/**
	* Gets both the default target list and any targets in the action currently being played.
	* @param includeDefaults	If true is passed, list includes the Fuse instance's default target list plus active action targets.
	* @return Array of targets currently being handled by the playing or paused action, plus the Fuse instance's default target list if true was passed.<br>
	* <br>If the Fuse instance queried is stopped, an empty array is returned.
	* @see #target
	* @see #addTarget
	* @see #removeTarget
	*/
	public function getActiveTargets(includeDefaults:Boolean):Array
	{
		if (_sState!='playing' && _sState!='paused') return ([]);
		var targetList:Array;
		if (includeDefaults==true) targetList = _aDefaultTargs.slice();
		else targetList = [];
		return ( FuseItem(this[_nIndex]).getActiveTargets(targetList) );
	}
	
	// ----------------------------------------------------------------------------------------------------
	//       Array-style Methods
	// ----------------------------------------------------------------------------------------------------
	
	/**
	* Returns a copy of Fuse as a new Fuse instance.
	* @return 	new Fuse instance with default settings and actions.
	* @see	#push
	* @see	#pushTween
	* @see	#pop
	* @see	#unshift
	* @see	#shift
	* @see	#splice
	* @see	#slice
	* @see	#reverse
	* @see	#clone
	*/
	public function clone():Fuse
	{
		var initObjs:Array = [];
		for (var i:Number=0; i<length; i++) {
			initObjs.push(FuseItem(this[i]).getInitObj());
		}
		var f:Fuse = new Fuse();
		f.push.apply(f,initObjs);
		f.scope = scope;
		f.target = target;
		return f;
	}
	
	/**
	* Pushes arguments into Fuse instance.
	* @return 	new length of Fuse instance
	* @see	#pushTween
	* @see	#pop
	* @see	#unshift
	* @see	#shift
	* @see	#splice
	* @see	#slice
	* @see	#reverse
	* @see	#clone
	*/
	public function push():Number
	{
		this.splice.apply(this, (new Array(length, 0)).concat(arguments));
		return length;
	}
	
	/**
	* Lets you add an item to the Fuse in ZigoEngine.doTween() syntax. Pushes tween arguments into Fuse instance and accepts the same arguments as ZigoEngine.doTween().
	* @param targets		tween target object or array of target objects
	* @param props			tween property or Array of properties
	* @param pEnd			tween end-value or Array of corresponding end-values
	* @param seconds		tween duration
	* @param ease			function, shortcut-string, or custom-easing-panel object
	* @param delay			seconds to wait before performing the tween
	* @param callback		function, string, or object
	* @return				new length of Fuse instance
	* @see com.mosesSupposes.fuse.ZigoEngine#doTween
	* @see	#push
	* @see	#pop
	* @see	#unshift
	* @see	#shift
	* @see	#splice
	* @see	#slice
	* @see	#reverse
	* @see	#clone
	*/
	public function pushTween(targets:Object, props:Object, pEnd:Object, seconds:Number, ease:Object, delay:Number, callback:Object):Number
	{
		this.push({__buildMode:true, tweenargs:arguments});
		return length;
	}
	
	/**
	* Removes last object placed into the Fuse instance.
	* @return	 	original object passed by user
	* @see	#push
	* @see	#pushTween
	* @see	#unshift
	* @see	#shift
	* @see	#splice
	* @see	#slice
	* @see	#reverse
	* @see	#clone
	*/
	public function pop():Object 
	{
		var o:Object = FuseItem(this[length-1]).getInitObj();
		this.splice(length-1, 1);
		return o;
	}
	
	/**
	* Removes argument objects from Fuse instance.
	* @return 		new length of Fuse instance
	* @see	#push
	* @see	#pushTween
	* @see	#pop
	* @see	#shift
	* @see	#splice
	* @see	#slice
	* @see	#reverse
	* @see	#clone
	*/
	public function unshift():Number
	{
		this.splice.apply(this, ((new Array(0, 0)).concat(arguments)));
		return length;
	}
	
	/**
	* Shifts position of object in Fuse order.
	* @return 		original object passed by user
	* @see	#push
	* @see	#pushTween
	* @see	#pop
	* @see	#unshift
	* @see	#splice
	* @see	#slice
	* @see	#reverse
	* @see	#clone
	*/
	public function shift():Object
	{
		var o:Object = FuseItem(this[0]).getInitObj();
		this.splice(0, 1);
		return o;
	}
	
	/**
	* Used to insert or remove items. Works almost exactly like Array.splice. Removed actions are destroyed permanently, with the exception of nested Fuses.
	* @param startIndex			index in Fuse to begin removing objects
	* @param deleteCount		number of objects to delete from startIndex
	* @see	#push
	* @see	#pushTween
	* @see	#pop
	* @see	#unshift
	* @see	#shift
	* @see	#slice
	* @see	#reverse
	* @see	#clone
	*/
	public function splice(startIndex:Number, deleteCount:Number):Void
	{
		this.stop(true);
		var si:Number = Number(arguments.shift());
		if (si<0) si = length+si;
		deleteCount = Number(arguments.shift());
		var newItems:Array = new Array();
		for (var i:Number=0; i<arguments.length; i++) { 
			// convert new objs to FuseItems before splicing
			var item:Object = (arguments[i] instanceof Fuse) ? arguments[i] : new FuseItem((si+i), arguments[i], _nID);
			this.addEventListener('onStop', item);
			this.addEventListener('evtSetStart', item);
			newItems.push(item);
		}
		//deleteItems
		var deadItems:Array = (super.splice.apply(this, ((new Array(si,deleteCount)).concat(newItems))));
		for (var j:String in deadItems) {
			this.removeEventListener('onStop', deadItems[j]);
			this.removeEventListener('evtSetStart', deadItems[j]);
			if (deadItems[j] instanceof Fuse) {
				Fuse(deadItems[j]).removeEventListener('onComplete', _oDel1); // safety
				// does not destroy nested Fuse during removal
			}
			else { 
				// destroy item
				FuseItem(deadItems[j]).destroy();
				delete this[FuseItem(deadItems[j])._nItemID]; 
			}
		}
		// renumber items
		for (var i:Number=0; i<length; i++) {
			FuseItem(this[i])._nItemID = i;
		}
	}
	
	/**
	* Returns a new array instance consisting of a range of elements from the original array without modifying the original array. The array returned by this method includes the indexA element and all elements up to, but not including indexB element. If no parameters are passed, a duplicate of the original array is generated. For more information, see the Flash help explanation of Array.slice.
	* @param indexA:Number (optional)	A number specifying the index of the starting point for the slice. If start is negative, the starting point begins at the end of the array, where -1 is the last element.
	* @param indexB:Number (optional)	A number specifying the index of the ending point for the slice. If you omit this parameter, the slice includes all elements from the starting point to the last element of the array. If end is negative, the ending point is specified from the end of the array, where -1 is the last element.
	* @return		 					an array consisting of a range of elements from the original array.
	* @see	#push
	* @see	#pushTween
	* @see	#pop
	* @see	#unshift
	* @see	#shift
	* @see	#splice
	* @see	#reverse
	* @see	#clone
	*/
	public function slice(indexA:Number, indexB:Number):Array
	{
		var a:Array = super.slice(indexA,indexB);
		var initObjs:Array = new Array();
		for (var i:Number=0; i<arguments.length; i++) {
			initObjs.push(FuseItem(this[i]).getInitObj());
		}
		return initObjs;
	}
	
	/**
	* Reverse the sequence of the Fuse
	* @see	#push
	* @see	#pushTween
	* @see	#pop
	* @see	#unshift
	* @see	#shift
	* @see	#splice
	* @see	#slice
	* @see	#clone
	*/
	public function reverse():Void
	{
		this.stop(true);
		super.reverse();
		// renumber
		for (var i:Number=0; i<length; i++) FuseItem(this[i])._nItemID = i;
	}
	
	/**
	* Traces specific or all objects contained within the fuse
	* @param indexA:Number (optional) A number specifying the index of the starting point for the slice. If start is negative, the starting point begins at the end of the array, where -1 is the last element.
	* @param indexB:Number (optional) - A number specifying the index of the ending point for the slice. If you omit this parameter, the slice includes all elements from the starting point to the last element of the array. If end is negative, the ending point is specified from the end of the array, where -1 is the last element.
	* @see #toString
	* @see #id
	* @see #label
	*/
	public function traceItems(indexA:Number, indexB:Number):Void
	{
		var s:String = '';
		var a:Array = super.slice(indexA,indexB);
		s+= ('-Fuse#'+String(_nID)+' traceItems:'+'\n----------\n');
		for (var i:Number=0; i<a.length; i++) {
			if (a[i] instanceof Fuse){
				s+= ('-Fuse#'+String(_nID)+' #'+_nID+'>Item#'+i+': [Nested Fuse] '+a[i])+'\n';
			}else{
				s+= (a[i])+'\n';
			}
		}
		s+= ('----------');
		FuseKitCommon.output(s);
	}
	
	/**
	* @return a string representation of the fuse including its id, and label if defined.
	* @see #traceItems
	* @see #id
	* @see #label
	*/
	public function toString():String { return 'Fuse#'+String(_nID)+((label!=undefined)?(' "'+label+'"'):'')+' (contains '+length+' items)'; }
	
	
	// ----------------------------------------------------------------------------------------------------
	//       Play-Control Methods
	// ----------------------------------------------------------------------------------------------------
	
	/**
	* General: Presets start-properties like <code>start_x</code> in all or specific items. 
	* @description In this example a sequence is set up and all start props are set, although the Fuse may not be used until later.
	* <pre>var f:Fuse = new Fuse();
	* f.target = clip1;
	* f.push({ start_alpha:0 }); // fade up
	* f.push({ x:'100', start_scale:150}); // scale down and slide
	* f.setStartProps();</pre>
	* If you want to set start props as the Fuse is started, you can pass <code>setStartProps</code> parameters to {@link #start}.
	* @param nothing/null/{@link com.mosesSupposes.fuse.FuseKitCommon#ALL} to set all start props in the Fuse. 
	* To specify some actions while excluding others, pass an array of item indices/labels or a series of indices/labels as separate parameters.
	* @see #start
	*/
	public function setStartProps(trueOrItemIDs:Object):Void
	{
		var all:Boolean = (arguments.length==0 || trueOrItemIDs===true || trueOrItemIDs==FuseKitCommon.ALL);
		dispatchEvent({target:this, 
					   type:'evtSetStart',
					   all:all,
					   filter:(trueOrItemIDs instanceof Array) ? trueOrItemIDs : arguments,
					   curIndex:((state=='playing') ? _nIndex : -1),
					   targs:_aDefaultTargs,
					   scope:scope});
	}
	
	/**
	* Play-control: Begins sequence play at index 0, with option to set start props prior to play.
	* @description In this example all start props are set during start by passing true.
	* <pre>var f:Fuse = new Fuse();
	* f.target = clip1;
	* f.push({ start_alpha:0 }); // fade up
	* f.push({ x:'100', start_scale:150}); // scale down and slide
	* f.start(true);</pre>
	* @param 	setStart	A {@link #setStartProps} call is generated from all arguments before the Fuse begins playing.
	* @see #stop
	* @see #pause
	* @see #resume
	* @see #skipTo
	*/
	public function start(setStart:Object):Void
	{
		close();
		this.stop(true);
		this._sState = 'playing';
		if (length==0) {
			advance(false,true); // fires onComplete, state must be playing
		}
		if (setStart!=null && setStart!=false){
			setStartProps.apply(this,arguments);
		}
		dispatchEvent({target:this, type:'onStart'});
		if (OUTPUT_LEVEL>1) FuseKitCommon.output('-Fuse#'+String(_nID)+'  start.');
		playCurrentItem();
	}
	
	/**
	* Play-control: Stops a playing or paused Fuse instance and resets the play-index to 0.
	* @see #start
	* @see #pause
	* @see #resume
	* @see #skipTo
	*/
	public function stop():Void
	{
		if(_sState!='stopped') { 
			for (var i:Number=0; i<length; i++) {
				// stop all triggered items to kill trailing tweens.
				if (i==_nIndex || (FuseItem(this[i]).hasTriggerFired())==true) FuseItem(this[i]).stop();
			}
		}
		else {
			// prevents dispatch if stop called while stopped.
			arguments[0] = true; 
		}
		if ((this[_nIndex]) instanceof Fuse) {
			Fuse(this[_nIndex]).removeEventListener('onComplete', _oDel1);
		}
		this._sState = 'stopped';
		// arg true internal only, don't broadcast stop if stopped.
		if (!(arguments[0]===true && this._sState=='stopped')) { 
			dispatchEvent({target:this, type:'onStop'});
			if (OUTPUT_LEVEL>1) FuseKitCommon.output('-Fuse#'+String(_nID)+'  stop.');
		}
		_nIndex = 0;
		clearInterval(_nDelay);
		_nTimeCache = _nDelay = -1;
	}
	
	/**
	* Play-control: Starts Fuse at a particular index/label.
	* @description <pre>var f:Fuse = new Fuse();
	* f.target = clip1;
	* f.push({ start_alpha:0 });
	* f.push({ x:'100', label:"slideRight"});
	* //later...
	* f.skipTo("slideRight"); // same as f.skipTo(1);</pre>
	* @param indexOrLabel		numerical item index or label string. Pass a negative index to count back from end, like -1 for last item.
	* @see #start
	* @see #stop
	* @see #pause
	* @see #resume
	*/
	public function skipTo(indexOrLabel:Object):Void
	{
		close();
		var index:Number;
		// label 
		if (typeof indexOrLabel=='string') { 
			index = -1;
			for (var i:Number=0; i<length; i++) {
				if ((FuseItem(this[i]).getLabel())==String(indexOrLabel)) {
					index = i;
					break;
				}
			}
			if (index==-1) {
				if (OUTPUT_LEVEL>0) FuseKitCommon.error('102',String(indexOrLabel));
			}
		}
		else {
			index = Number(indexOrLabel);
		}
		if (_global.isNaN(index)==true || Math.abs(index)>=length) {
			// changed this from triggering onComplete to just failing, it's a mistake and should not work.
			if (OUTPUT_LEVEL>0) FuseKitCommon.error('103',String(indexOrLabel));
		}
		if (index<0) index = Math.max(0, length + index);
		// hidden second arg passed by FuseItem
		if (index==_nIndex && arguments[1]===true) { 
			if (OUTPUT_LEVEL>0) FuseKitCommon.error('104',String(indexOrLabel),_nIndex);
		}
		if ((this[_nIndex]) instanceof Fuse) {
			Fuse(this[_nIndex]).removeEventListener('onComplete', _oDel1);
		}
		// (Item will be replayed if skipTo called on current item)
		FuseItem(this[_nIndex]).stop(); 
		_nIndex = index;
		var s:String = _sState;
		this._sState = 'playing';
		// skipTo is being used to start the Fuse
		if (s=='stopped') dispatchEvent({target:this, type:'onStart'}); 
		playCurrentItem();
		if (OUTPUT_LEVEL>1) FuseKitCommon.output('skipTo:'+index);
	}
	
	/**
	* Play-control: Pauses a playing Fuse instance and its running tweens. Waits for {@link #resume} call to proceed.
	* @see #start
	* @see #stop
	* @see #resume
	* @see #skipTo
	*/
	public function pause():Void
	{
		if(_sState=='playing'){
			FuseItem(this[_nIndex]).pause();
			if (_nTimeCache!=-1) {
				// remaining time in delay
				_nTimeCache -= getTimer(); 
				clearInterval(_nDelay);
			}
			this._sState = 'paused';
			if (OUTPUT_LEVEL>1) FuseKitCommon.output('-Fuse#'+String(_nID)+'  pause.');
			dispatchEvent({target:this, type:'onPause'});
		}
	}
	
	/**
	* Resumes a paused Fuse instance and its animations. Attempts to correct for animations that have been disrupted during pause.
	* @see #start
	* @see #stop
	* @see #pause
	* @see #skipTo
	*/
	public function resume():Void
	{
		if (_sState!='paused') return; // Behavior change from 1.0: only accept resume calls if paused!
		close();
		this._sState = 'playing';
		if (OUTPUT_LEVEL>1) FuseKitCommon.output('-Fuse#'+String(_nID)+'  resume.');
		dispatchEvent({target:this, type:'onResume'});
		if (_nTimeCache!=-1) {
			clearInterval(_nDelay);
			this._nTimeCache = getTimer()+_nTimeCache;
			this._nDelay = setInterval(Delegate.create(this, playCurrentItem), _nTimeCache, true);
		}
		// resume
		FuseItem(this[_nIndex]).pause(true); 
	}
	
	// ----------------------------------------------------------------------------------------------------
	//       Private Methods
	// ----------------------------------------------------------------------------------------------------
	
	/**
	* Internal handler called by items on completion.
	* @param wasTriggered 	is sent true when an item advanced prematurely using the trigger property completes and is used to track the 
	* final completion of a Fuse in which animations trail beyond the sequence end.
	* @param silentStop 	starting a 0-item Fuse triggers this param so that only the <code>onComplete</code> event gets fired.
	*/
	private function advance(wasTriggered:Boolean, silentStop:Boolean):Void
	{
		var isLastFinal:Boolean = false;
		if (_nIndex==length-1) {
			for (var i:Number=length-1; i>-1; i--) {
				if (FuseItem(this[i])._nPlaying>-1) {
					return; // an overlapping item (one containing a trigger) is not finished playing.
				}
			}
			isLastFinal = true;
		}
		if (wasTriggered==true && isLastFinal==false) { // wasTriggered calls are sent only for the above check. 
			return;
		}

		if ((this[_nIndex]) instanceof Fuse) {
			Fuse(this[_nIndex]).removeEventListener('onComplete', _oDel1);
		}
		if (++_nIndex>=length) {
			this.stop(silentStop);
			if (Fuse.OUTPUT_LEVEL>1) FuseKitCommon.output('-Fuse#'+String(_nID)+' complete.');
			dispatchEvent({target:this, type:'onComplete'});
			if (autoClear==true || (autoClear!==false && AUTOCLEAR==true)) destroy();
			return;
		}
		if (Fuse.OUTPUT_LEVEL>1) FuseKitCommon.output('-Fuse#'+String(_nID) + ' advance: '+_nIndex);
		dispatchEvent({target:this, type:'onAdvance'});
		playCurrentItem();
	}
	
	/**
	* Internal helper that triggers <code>startItem()</code> in currently active item.
	* @param postDelay		true is sent when a delay has completed.
	*/
	private function playCurrentItem(postDelay:Boolean):Void
	{
		clearInterval(_nDelay);
		if (postDelay!==true) {
			var d:Number = (FuseItem(this[_nIndex]).evalDelay(scope) || 0);
			//if (_nIndex==0 && d==0) d = .01;// super-tiny delay at Fuse start fixes a number of glitches.
			if (d>0) {
				this._nTimeCache = getTimer()+(d*1000);//used during pause.
				this._nDelay = setInterval(Delegate.create(this, playCurrentItem), d*1000, true);
				return;
			}
		}
		_nTimeCache = _nDelay = -1;
		if ((this[_nIndex]) instanceof Fuse) {
			if (_oDel1==null) _oDel1 = Delegate.create(this,advance);
			Fuse(this[_nIndex]).addEventListener('onComplete', _oDel1);
		}
		var propsTweened:String = (FuseItem(this[_nIndex]).startItem(_aDefaultTargs, scope));
		if (Fuse.OUTPUT_LEVEL>1) FuseKitCommon.output('-Fuse#'+String(_nID)+' props tweened: '+propsTweened);
	}
	
	/**
	* Internal event used when the fuse is nested in a parent fuse. (Polymorphism - this is a FuseItem method that only appears in Fuse for the nested instance case).
	*/
	private function evtSetStart(o:Object):Void
	{
		setStartProps.apply(this, o.filter);
	}
	
	/**
	* FuseItem method used by a Fuse only when the it is nested in a parent Fuse.
	* @param targs
	* @param scope
	*/
	public function startItem(targs:Array, scope:Object):Void
	{
		// adopt scope and targs from parent if none set. This is really rough, 
		// ultimately it ought to be written to cache the original values then restore.
		if (target==null) target = targs; 
		if (scope==null) scope = scope;
		this.start();
	}
	
	/**
	 * Simple Syntax:Generate a new Fuse and begin intercepting tween calls until {@link com.mosesSupposes.fuse.Fuse#close} is called.
	 * @description	Simple Syntax is an alternative way to construct Fuse sequences. 
	 * Its primary uses are 1. Clear method-call sequencing and 2. An easy way for non-advanced coders to set up sequences.
	 * @usage
	 * <pre>
	 * // Example 1: Can be used to enforce a clear, strict order of timed events
	 * Fuse.open();
	 *  Fuse.addCommand (mainMenu, "draw", menuXML);
	 *  Fuse.addCommand ("delay", .5);
	 *  Fuse.addCommand (contentPage, "loadContent", firstItem);
	 *  Fuse.addCommand (screenDisplay, "exposeLayout");
	 *  Fuse.addCommand ("delay", 2);
	 *  Fuse.addCommand (this, "onResize");
	 *  Fuse.addCommand (Logger, "output", "Setup sequence complete.", 0);
	 * Fuse.close();
	 * 
	 * // Example 2: Simple Syntax with shortcut tweens
	 * Fuse.open();
	 *  box_mc.slideTo(150,150, 1);
	 *  Fuse.openGroup();
	 *   box_mc.scaleTo(250, 1);
	 *   box_mc.brightnessTo(-50, 2);
	 *  Fuse.closeGroup();
	 *  box_mc.colorTo(0x6633FF, 1);
	 * Fuse.closeAndStart();
	 * </pre>
	 * <br>
	 * You may retrieve the Fuse instance created, or reopen an existing Fuse:
	 * <pre>var f:Fuse = Fuse.open(); // store a reference to the Fuse
	 * // later...
	 * Fuse.open(f); // reopen existing
	 * // or...
	 * Fuse.open(0); // open Fuse with id 0
	 * // or...
	 * Fuse.open("introSequence"); // open Fuse with the label "introSequence"</pre>
	 * <br>
	 * If you mostly use simple syntax and don't reuse your Fuses, it's recommended that you set {@link #AUTOCLEAR} to true to avoid memory buffering.
	 * @param fuseOrID	(Optional) Pass an existing Fuse, or its id or label to reopen it.
	 * @return 			The opened Fuse instance that tween calls will be routed to until close() is called.
	 * @see	#openGroup
	 * @see	#closeGroup
	 * @see	#close
	 * @see	#closeAndStart
	 * @see	#startRecent
	 * @see	#addCommand
	 * @see	#id
	 * @see	#label
	 */ 
	public static function open(fuseOrID:Object):Fuse // returns Fuse instance added to until Fuse.close() is called.
	{
		var _ZigoEngine:Function = _global.com.mosesSupposes.fuse.ZigoEngine;
		if (_ZigoEngine==undefined) {
			FuseKitCommon.error('106');
			return null;
		}
		else {
			(_ZigoEngine).register(Fuse, FuseItem);
		}
		if (_oBuildMode==null) {
			_oBuildMode = {
				curID:-1,
				prevID:-1,
				curGroup:null
			};
		}
		else if (_oBuildMode!=null && _oBuildMode.curID>-1) {
			close();
		}
		if (fuseOrID!=null) {
			if (fuseOrID instanceof Fuse) {
				_oBuildMode.curID = fuseOrID.id;
			}
			else if (getInstance(fuseOrID)!=null) {
				_oBuildMode.curID = getInstance(fuseOrID).id;
			}
			else {
				FuseKitCommon.error('107');
				return null;
			}
		}
		else {
			_oBuildMode.curID = (new Fuse()).id;
		}
		_oBuildMode.prevID = _oBuildMode.curID;
		return getInstance(_oBuildMode.curID);
	}
	
	/**
	* Simple Syntax: Begins a new animation group of simultaneous actions.
	* @description If <code>Fuse.openGroup()</code> can be called in place of <code>Fuse.open()</code>.<br><br>
	* If <code>Fuse.openGroup()</code> is called while a previous group was open, the preceding group is closed automatically.
	* <pre>// use in place of Fuse.open() to begin a new Fuse.
	* Fuse.openGroup();
	*  clip1.tween("_x","100");
	*  clip2.tween("_scale",200);
	* Fuse.openGroup(); // you can skip closeGroup if opening another group.
	*  clip1.tween("_x","-100");
	*  clip2.tween("_scale",100);
	* Fuse.closeAndStart(); // you can skip closeGroup here too.
	* </pre>
	* @param fuseOrID:Fuse		(Optional) an existing Fuse or Fuse's id or label in which to open the new group.
	* @return					The currently open fuse instance or a new Fuse if openGroup was called prior to open().
	* @see	#open
	* @see	#closeGroup
	* @see	#close
	* @see	#closeAndStart
	* @see	#startRecent
	* @see	#addCommand
	* @see	#id
	* @see	#label
	*/
	public static function openGroup(fuseOrID:Object):Fuse
	{
		// allow openGroup() to open a new sequence.
		if (!(_oBuildMode!=null && _oBuildMode.curID>-1)) open(fuseOrID); 
		else if (_oBuildMode.curGroup!=null) closeGroup();
		_oBuildMode.curGroup = new Array();
		return getInstance(_oBuildMode.curID);
	}
	
	/**
	* Simple Syntax: Closes an action group started by {@link #openGroup}.
	* @description	May be omitted if followed by <code>Fuse.close</code> or <code>Fuse.closeAndStart</code>.<br><br>
	* If <code>Fuse.openGroup()</code> is called while a previous group was open, the preceding group is closed automatically and the <code>closeGroup</code> command can be skipped.
	* <pre>Fuse.open();
	* clip1.tween("_x","100");
	* Fuse.openGroup();
	*  clip1.tween("_x","-100");
	*  clip2.tween("_scale",200);
	* Fuse.closeGroup();
	* clip1.scaleTo(0);
	* clip2.scaleTo(0);
	* Fuse.closeAndStart();</pre>
	* @see	#open
	* @see	#openGroup
	* @see	#close
	* @see	#closeAndStart
	* @see	#startRecent
	* @see	#addCommand
	*/
	public static function closeGroup():Void
	{
		if (_oBuildMode.curGroup==null || !(_oBuildMode!=null && _oBuildMode.curID>-1)) return;
		getInstance(_oBuildMode.curID).push(_oBuildMode.curGroup);
		_oBuildMode.curGroup = null;
	}
	
	/**
	* Simple Syntax: Completes the Fuse generated by {@link com.mosesSupposes.fuse.Fuse#open}.
	* @description	It is important that you complete each Fuse created using <code>Fuse.open()</code> using either <code>Fuse.close()</code> or <code>Fuse.closeAndStart()</code>. You cannot call <code>start</code> on a Fuse instance while Fuse is open.
	* <pre>var runSetup:Fuse = Fuse.open();
	* Fuse.addCommand(this, "callbackOne");
	* Fuse.addCommand("delay", .25);
	* Fuse.addCommand(this, "callbackTwo");
	* Fuse.addCommand("delay", .25);
	* Fuse.addCommand(this, "callbackThree");
	* Fuse.close();
	* 
	* // later in program...
	* runSetup.start(); // reference the Fuse created
	* </pre>
	* @see	#open
	* @see	#openGroup
	* @see	#closeGroup
	* @see	#closeAndStart
	* @see	#startRecent
	* @see	#addCommand
	*/
	public static function close():Void
	{
		if (!(_oBuildMode!=null && _oBuildMode.curID>-1)) return;
		if (_oBuildMode.curGroup!=null) closeGroup();
		_oBuildMode.curID = -1;
	}
	
	/**
	* Simple Syntax: Close the open Fuse instance and start it playing.
	* @description <pre>var runSetup:Fuse = Fuse.open();
	* clip1.fadeOut();
	* clip2.fadeOut();
	* clip3.fadeOut();
	* Fuse.closeAndStart();</pre>
	* @param 	setStart	A {@link #setStartProps} call is generated from all arguments before the Fuse begins playing.
	* @see	#open
	* @see	#openGroup
	* @see	#closeGroup
	* @see	#close
	* @see	#startRecent
	* @see	#addCommand
	*/
	public static function closeAndStart(setStart:Object):Void
	{
		if (!(_oBuildMode!=null && _oBuildMode.curID>-1)) return;
		var f:Fuse = getInstance(_oBuildMode.curID);
		close();
		f.start.apply(f, arguments);
	}
	
	/**
	* Simple Syntax: Restarts the Fuse most recently created using Fuse.{@link #open}().
	* @param 	setStart	A {@link #setStartProps} call is generated from all arguments before the Fuse begins playing.
	* @see	#open
	* @see	#openGroup
	* @see	#closeGroup
	* @see	#close
	* @see	#closeAndStart
	* @see	#addCommand
	*/
	public static function startRecent(setStart:Object):Void
	{
		var f:Fuse = getInstance(_oBuildMode.prevID);
		if (f!=null) f.start.apply(f, arguments);
		else FuseKitCommon.error('108');
	}
	
	/**
	* Simple Syntax: Multi-purpose method to add an inline Fuse command, delay, or function-call to the open Fuse.
	* @description <pre>var f:Fuse = new Fuse();
	* 
	* // callback: scope, func, args
	* Fuse.addCommand(this, "setItemData", 0, "Submit", true);
	* 
	* // delay
	* Fuse.addCommand("delay", .5);
	* 
	* // inline Fuse play-command: forces Fuse to loop by restarting
	* Fuse.addCommand("start");
	* 
	* Fuse.closeAndStart();
	* </pre>
	* @param commandOrScope		may be: <code>'delay','start','stop','pause','resume','skipTo','setStartProps'</code> or in the case of a function-call a scope such as <code>this</code>.
	* @param indexOrFunc		<code>'delay'</code>:number of seconds. <code>'skipTo'</code>:destination index/label. For function-call, a string of the function name such as <code>'trace'</code>
	* @param argument			for function-call, any number of arguments can follow and will be passed to the function when it's called.
	* @see	#open
	* @see	#openGroup
	* @see	#closeGroup
	* @see	#close
	* @see	#closeAndStart
	* @see	#startRecent
	*/
	public static function addCommand(commandOrScope:Object, indexOrFunc:Object, argument:Object):Void
	{
		if (!(_oBuildMode!=null && _oBuildMode.curID>-1)) return;
		var into:Array = (_oBuildMode.curGroup!=null) ? _oBuildMode.curGroup : getInstance(_oBuildMode.curID); // New feature: allow addCommand within groups
		if (typeof commandOrScope=='string') { // assume it's a command
			if (_oBuildMode.curGroup!=null && commandOrScope!='delay') {
				FuseKitCommon.error('109',String(commandOrScope));
				return;
			}
			var validCommands:String = '|delay|start|stop|pause|resume|skipTo|setStartProps|'; // "delay" command is specific to simple syntax
			if (validCommands.indexOf('|'+commandOrScope+'|')==-1 || ((commandOrScope=='skipTo' || commandOrScope=='delay') && indexOrFunc==undefined)) {
				if (OUTPUT_LEVEL>0) FuseKitCommon.error('110',String(commandOrScope));
			}
			else {
				into.push({__buildMode:true, command:commandOrScope, commandargs:indexOrFunc});
			}
		}
		else { 
			// assume it's a function-call
			into.push({__buildMode:true, scope:commandOrScope, func:indexOrFunc, args:arguments.slice(2)});
		}
	}
	
	// -- internal --
	
	/**
	* @exclude
	* Internal use only. This is the method ZigoEngine uses to route tween calls into an open Fuse instance after <code>Fuse.open()</code>.
	* @return		true if Fuse is in build-mode
	*/
	public static function addBuildItem(args:Array):Boolean
	{
		if (!(_oBuildMode!=null && _oBuildMode.curID>-1)) return false;
		var into:Array = (_oBuildMode.curGroup!=null) ? _oBuildMode.curGroup : getInstance(_oBuildMode.curID);
		if (args.length==1 && typeof args[0]=='object') {
			// Object syntax can be mixed with simple syntax by using Fuse.open(); with commands like my_mc.tween({x:'100'});
			into.push(args[0]);
		}
		else {
			into.push({__buildMode:true, tweenargs:args});
		}
		return true;
	}
	
	/**
	* Internal, used to add a Fuse instance to the _aInstances array.
	* @param 	Fuse instance
	* @return 	internal index used as Fuse's id
	*/
	private static function registerInstance(s:Fuse):Number
	{
		if(_aInstances==null) _aInstances = new Array();
		return _aInstances.push(s)-1;
	}
	
	/**
	* Interal, used to remove a Fuse instance from the _aInstances array.
	* @param id
	* @param isDestroyCall
	*/
	private static function removeInstanceAt(id:Number, isDestroyCall:Boolean):Void
	{
		if (isDestroyCall!=true) {
			Fuse(_aInstances[id]).destroy();
		}
		delete _aInstances[id];
	}
}